﻿using Microsoft.AspNetCore.Http;
using ThresholdAssistant.Tools;
using ThresholdAssistant.Tools.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace ThresholdAssistant.Http.Extensions
{
    /// <summary>
    /// 转换扩展
    /// </summary>
    public static class ConvertExtensions
    {
        /// <summary>
        /// 通配的头部信息
        /// </summary>
        private static readonly string _generalHeaderKey = "-";

        /// <summary>
        /// 请求头白名单Key列表
        /// </summary>
        private static readonly string[] _whiteKeyList = new string[] { "merchant_no", "merchantNo", "token", "postPosition", "OAuth", "X-Real-IP","servletPath",
            "x-traceId-header","X-Forwarded-For","X-Forwarded-Proto","X-Forwarded-Prefix","X-Forwarded-Port","X-Forwarded-Host","sign","method","merchantLableNo",
            "current-timestamp", "cmd-timestamp","wx-protocol-type" };

        /// <summary>
        /// 转换头部信息
        /// </summary>
        /// <param name="httpContext">http上下文</param>
        /// <returns></returns>
        public static Dictionary<string, string> ToHeaders(this IHttpContextAccessor httpContext)
        {
            var headerDic = new Dictionary<string, string>();
            var headers = httpContext?.HttpContext?.Request?.Headers;
            if (headers != null && headers.Any())
            {
                var request = httpContext.HttpContext.Request;
                if (request.Host.HasValue)
                {
                    headerDic.AddHeader("x-host", request.Host.Value);
                }

                headerDic.AddHeader("x-path", request.Path);//接口请求路径
                headerDic.AddHeader("x-scheme", request.Scheme);//请求协议
                headerDic.AddHeader("x-method", request.Method);//请求方法
                foreach (var header in headers)
                {
                    //如果即不再白名单也不符合通配规则的时候直接过滤
                    if ((Regex.IsMatch(header.Key, "[A-Z]") || header.Key.IndexOf(_generalHeaderKey) <= 0) &&
                        !_whiteKeyList.Any(e => e.Equals(header.Key, StringComparison.CurrentCultureIgnoreCase)))
                    {
                        continue;
                    }
                    else
                    {
                        if (header.Key == "servletPath")
                        {
                            //网关下游接口地址
                            headerDic.AddHeader("x-servlet-path", header.Value);
                        }
                    }
                    headerDic.AddHeader(header.Key, header.Value);
                }
            }
            return headerDic;
        }

        /// <summary>
        /// 添加头部信息
        /// </summary>
        /// <param name="headers">头部信息</param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public static void AddHeader(this Dictionary<string, string> headers, string key, string value)
        {
            //非空校验
            if (headers == null || string.IsNullOrEmpty(key) || string.IsNullOrEmpty(value) || headers.ContainsKey(key))
                return;

            headers.Add(key, value);
        }

        /// <summary>
        /// 追加头部信息
        /// </summary>
        /// <param name="source"></param>
        /// <param name="headers">头部信息</param>
        public static Dictionary<string, string> AddHeaders(this Dictionary<string, string> source, Dictionary<string, string> headers)
        {
            if (headers != null && headers.Any())
            {
                if (source == null || !source.Any())
                {
                    source = new Dictionary<string, string>();
                }
                headers.ForEach(header => source.AddHeader(header.Key, header.Value));
            }
            return source;
        }

        /// <summary>
        /// 转换业务流水号
        /// </summary>
        /// <param name="headers">头部信息</param>
        /// <param name="serialNo">业务流水号</param>
        /// <returns></returns>
        public static string ToSerialNo(this Dictionary<string, string> headers, string serialNo)
        {
            if (string.IsNullOrEmpty(serialNo))
            {
                if (headers != null && headers.ContainsKey("x-traceId-header"))
                {
                    //绑定网关传过来的业务流水号
                    serialNo = headers["x-traceId-header"];
                }

                if (string.IsNullOrEmpty(serialNo))
                {
                    serialNo = SnowflakeNoUtil.GetSerialNo();
                }
            }
            return serialNo;
        }
    }
}